/**
 * @file swei_opcode.c
 * @brief 
 * @author  ()
 * @version 1.0
 * @date 2024-09-13
 * 
 * @copyright Copyright (C) 2019 Queclink Wireless Solutions (ShenZhen) Co., Ltd. All Rights Reserved.
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2024-09-13 <td>1.0     <td>     <td>内容
 * </table>
 */
#include "include/port/swei_log.h"
#include "include/swei_opcode.h"
#include "include/swei_common.h"
#include "include/swei_downlink.h"

#include "global.h"

/* 保存最大指令对应关系的个数 */
#define MAX_SAVE_CMD_OPCODE_NUM 8

/* 保存cmd_id <--> 指令操作码对应关系, 不初始化也可以还是屎山代码初始化一下吧 */
static NET_PROTOCOL_CMD_OPCODE g_st_save_cmd_opcode[MAX_SAVE_CMD_OPCODE_NUM] = {
    {0x00, 0x00},
    {0x00, 0x00},
    {0x00, 0x00},
    {0x00, 0x00},
    {0x00, 0x00},
    {0x00, 0x00},
    {0x00, 0x00},
    {0x00, 0x00}};

/*****************************************************************************
 * Function      : tbox_netprotocol_save_cmd_opcode
 * Description   : 保存下行指令和指令操作码的对应关系
 * Input         : cmd_id:下行指令id        cmd_opcode:该指令id对应的操作码
 * Output        : None
 * Return        :
 * Others        :
 * Record
 * 1.Date        : 20230712
 *   Author      : yanfeng
 *   Modification: Created function
 *****************************************************************************/
int32_t tbox_netprotocol_save_cmd_opcode(uint16_t cmd_id, uint16_t cmd_opcode)
{
    uint8_t loop = 0;

    /* 操作都在netProtocol中进行,不做多线程的保护,并且指令处理之间也有先后顺序,指令处理结果不返回服务器不下下发新的指令
     * 如果后续修改者要在其他线程中同时修改,则需要增加读写锁或者互斥锁 */
    for (; loop < MAX_SAVE_CMD_OPCODE_NUM; loop++)
    {
        if ((g_st_save_cmd_opcode[loop].cmd_id == 0x00) && (g_st_save_cmd_opcode[loop].cmd_opcode == 0x00))
        {
            g_st_save_cmd_opcode[loop].cmd_id = cmd_id;
            g_st_save_cmd_opcode[loop].cmd_opcode = cmd_opcode;
            log_i("netprotocol save cmd opcode,[cmd_id:0x%x, opcode:0x%x]", cmd_id, cmd_opcode);
            break;
        }
    }

    if (loop == MAX_SAVE_CMD_OPCODE_NUM)
    {
        log_e("netprotocol no space save opcode!");
        return -NETPROTOCOL_NO_SPACE_SAVE_CMD_OPCODE;
    }
    else
    {
        return SUCC;
    }
}

/*****************************************************************************
 * Function      : tbox_netprotocol_get_cmd_opcode
 * Description   : 根据指令id获取对应的操作码
 * Input         : cmd_id:指令ID p_opcode:获取到的opcode        clear_flag:获取之后是否清除, true表示需要清除

   FALSE表示不要清除
 * Output        : None
 * Return        :
 * Others        :
 * Record
 * 1.Date        : 20230712
 *   Author      : yanfeng
 *   Modification: Created function
 *****************************************************************************/
int32_t tbox_netprotocol_get_cmd_opcode(uint16_t cmd_id, uint16_t *p_opcode, char clear_flag)
{
    uint8_t loop = 0;

    if (NULL == p_opcode)
    {
        log_e("get cmd opcode input null ptr!");
        return -NETPROTOCOL_INPUT_NULL;
    }

    /*  重点说明:
     *  clear_flag标志要根据实际业务需要进行正确的设置,如:某个指令在处理过程中有多个异常检查条件,每个异常检查条件都要给服务器回复一个消息
     *  并且单个异常条件不满足时不会return,此时clear_flag就不能清,因为后续的异常检查分支还要继续执行,在所有给服务器的回消息都处理完成之后再清理 */
    for (; loop < MAX_SAVE_CMD_OPCODE_NUM; loop++)
    {
        if (g_st_save_cmd_opcode[loop].cmd_id == cmd_id)
        {
            *p_opcode = g_st_save_cmd_opcode[loop].cmd_opcode;

            /* 获取之后清除,注意:对于指令的应答分为通用应答和指令处理之后的应答,这里的清除有滞后性
             * 封装通用应答消息时不能清楚,后续的指令应答还需要使用 */
            if (clear_flag == true)
            {
                log_w("clear cmd opcode,[cmd_id:0x%x opcode:0x%x]", g_st_save_cmd_opcode[loop].cmd_id, g_st_save_cmd_opcode[loop].cmd_opcode);
                g_st_save_cmd_opcode[loop].cmd_opcode = 0x00;
                g_st_save_cmd_opcode[loop].cmd_id = 0x00;
            }
            break;
        }
    }

    if (loop == MAX_SAVE_CMD_OPCODE_NUM)
    {
        *p_opcode = 0x00;
        return -NETPROTOCOL_NO_NO_CMD_OPCODE;
    }
    else
    {
        return SUCC;
    }
}
